#include "../../common.hpp"
#include <cstring>
#include <fcntl.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <unistd.h>

#define PORT 8085
#define MAX_CLIENTS 1024

int main() {
    int listen_fd = create_and_listen(PORT);
    if (listen_fd < 0) {
        return 1;
    }

    fd_set all_fds; // master fd_set，保存所有需要监听的fd
    fd_set read_fds;// 临时的fd_set，会作为select的参数被修改
    int max_fd;     // 记录当前所有fd中的最大值

    FD_ZERO(&all_fds);// 初始化master fd_set
    FD_SET(listen_fd, &all_fds);
    max_fd = listen_fd;

    while (1) {

        // 1. 准备临时的fd_set，因为select会修改它
        read_fds = all_fds;

        // 2. 调用select，阻塞等待事件发生
        int nready = select(max_fd + 1, &read_fds, NULL, NULL, NULL);
        if (nready < 0) {
            perror("select error");
            break;
        }

        // 3. 检查监听socket是否有新连接
        if (FD_ISSET(listen_fd, &read_fds)) {

            struct sockaddr_in client_addr;
            socklen_t client_len = sizeof(client_addr);
            int conn_fd = accept(listen_fd, (struct sockaddr *) &client_addr, &client_len);
            printf("conn_id : %d\n",conn_fd);
            if (conn_fd < 0) {
                perror("accept error");
            } else {
                printf("New connection from %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
                // 设置新连接为非阻塞
                int flag = fcntl(conn_fd, F_GETFL, 0);
                fcntl(conn_fd, F_SETFL, flag | O_NONBLOCK);

                // 将新连接的fd加入到master fd_set中
                FD_SET(conn_fd, &all_fds);
                if (conn_fd > max_fd) {
                    max_fd = conn_fd;
                }
            }
        }

        // 4. 检查其他已连接的socket是否有数据
        for (int i = 0; i <= max_fd; ++i) {
            if (i == listen_fd) {
                continue;// 跳过监听fd
            }
            if (FD_ISSET(i, &read_fds)) {
                char buffer[1024];
                memset(buffer, 0, sizeof(buffer));
                int n = read(i, buffer, sizeof(buffer) - 1);

                if (n <= 0) {// 客户端关闭连接或出错
                    if (n == 0) {
                        printf("Client fd %d disconnected\n", i);
                    } else {
                        perror("read error");
                    }
                    close(i);
                    FD_CLR(i, &all_fds);// 从master set中移除
                } else {                // 收到数据，回声
                    printf("Received from fd %d: %s\n", i, buffer);
                    write(i, buffer, n);
                }
            }
        }
    }
    close(listen_fd);
    return 0;
}